﻿namespace MapleRock.P2PEmulator.RGR
{
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Diagnostics;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading;
  using System.Windows.Forms;

  using MapleRock.P2PEmulator.Core;

  public partial class ExperimentPage : BasicRgrPage
  {
    public static readonly int SamplesPerExperiment;

    public static readonly int[] PeersNumber;

    public static readonly double[] MessageLossProb;

    public static readonly int[] Dimensions;

    public static readonly int[] MaxPeerLinks;

    private Thread experimentThread = null;

    static ExperimentPage()
    {
      ExperimentPage.PeersNumber = new int[] { 100, 1000, 5000, 10000, 25000, 50000, 75000 };
      ExperimentPage.MessageLossProb = new double[] { double.Epsilon, 0.001, 0.005, 0.01 };
      ExperimentPage.Dimensions = new int[] { 2, 4, 6, 10, 15 };
      ExperimentPage.MaxPeerLinks = new int[] { 3, 4, 6, 8, 10, 15, 20 };
      ExperimentPage.SamplesPerExperiment = ExperimentPage.PeersNumber.Length;
      Debug.Assert(
        ExperimentPage.PeersNumber.Length == ExperimentPage.SamplesPerExperiment,
        "ExperimentPage.PeersNumber.Length == ExperimentPage.SamplesPerExperiment");
    }

    public ExperimentPage()
    {
      this.InitializeComponent();
    }

    public override string RgrPageName
    {
      get { return "Эксперимент"; }
    }

    public override void OnPageEnter()
    {
      Debug.Assert(null == this.experimentThread, "null == this.experimentThread");

      this.experimentThread = new Thread(this.ExperimentThreadProc);
      this.experimentThread.Start();
    }

    public override void OnPageLeave()
    {
      Debug.Assert(null != this.experimentThread, "null != this.experimentThread");
      this.experimentThread = null;
    }

    public override void OnPageUnload()
    {
      base.OnPageUnload();

      if (this.experimentThread == null)
      {
        return;
      }

      if (this.experimentThread.IsAlive)
      {
        this.experimentThread.Abort();
        this.experimentThread = null;
      }
    }

    private void ExperimentThreadProc()
    {
      this.RgrPageContainer.DisableForwardButton();
      this.RgrPageContainer.DisableBackwardButton();

      bool IsExperimentCompleted = (RgrData.Instance.Experiment != null);
      if (!IsExperimentCompleted)
      {
        this.MakeExperiment();
        Debug.Assert(
          RgrData.Instance.Experiment != null,
          "RgrData.Instance.Experiment != null");
      }

      this.RgrPageContainer.EnableForwardButton();
      this.RgrPageContainer.EnableBackwardButton();
    }

    private void MakeExperiment()
    {
      ExperimentLog.Instance.SetLogControls(
        this, 
        this.experimentLogTextBox, 
        this.estimatedTimeLeftLabel,
        this.exprerimentProgressBar);
      ExperimentLog.Instance.ConfigureProgressBar(
        RgrExperiment.RunsPerSample * ExperimentPage.SamplesPerExperiment);

      ExperimentLog.Instance.LogEvent("************************************************");
      ExperimentLog.Instance.LogEvent("P2P CAN-Like Network Modelling System");

      RgrData.Instance.Experiment = new RgrExperiment(
        RgrData.Instance.VariableParameterIndex,
        RgrData.Instance.PeersNumberIndex,
        RgrData.Instance.MessageLossProbIndex,
        RgrData.Instance.DimensionsIndex,
        RgrData.Instance.MaxPeerLinksIndex);
      RgrData.Instance.Experiment.Go();

      ExperimentLog.Instance.LogEvent("Completed");
      ExperimentLog.Instance.LogEvent("************************************************");
    }
  }
}
